package com.g0dkar.leet.core.model.loaders;

import java.io.Serializable;
import java.util.Collection;

import javax.persistence.Id;

import com.g0dkar.leet.core.model.ClassMapping;
import com.g0dkar.leet.exception.LeetRuntimeException;
import com.g0dkar.leet.util.common.StringUtils;
import com.g0dkar.leet.util.reflection.ReflectionUtils;

/**
 * Creates {@link ClassMapping} objects from {@link Class Classes}. Every model class of a Leet Framework Application
 * must implement the {@link Serializable} interface.
 * 
 * @author g0dkar
 * 
 */
public class ClassMappingLoader implements ModelLoaderInterface<ClassMapping, Class<?>> {
	
	public ClassMapping load(Class<?> type) {
		System.out.println("[ClassMappingLoader] Serializable? " + Serializable.class.isAssignableFrom(type) + " // " + type.isAssignableFrom(Serializable.class));
		if (!Serializable.class.isAssignableFrom(type)) {
			System.out.println("Throwing exception...");
			throw new LeetRuntimeException("Every ClassMapping class must implement the %s interface.", Serializable.class.getName());
		}
		
		ClassMapping mapping = new ClassMapping();
		mapping.setName(type.getSimpleName());
		mapping.setDisplayName(StringUtils.classnameAsPhrase(mapping.getName()));
		mapping.setClassName(type.getCanonicalName());
		mapping.setSuperClassName(type.getSuperclass().getCanonicalName());
		mapping.setType(type);
		
		Collection<ReflectionUtils.Field> fields = ReflectionUtils.getFields(type);
		PropertyLoader propertyLoader = new PropertyLoader();
		for (ReflectionUtils.Field field : fields) {
			if (mapping.getIdField() == null) {
				if (field.field != null && field.field.isAnnotationPresent(Id.class)) {
					mapping.setIdField(field.name);
					continue;
				}
				else if ((field.name.equals("id") || field.name.equals("id" + mapping.getName()))) {
					mapping.setIdField(field.name);
					continue;
				}
			}
			
			mapping.add(propertyLoader.load(field));
		}
		
		if (mapping.getIdField() == null) {
			throw new LeetRuntimeException("ClassMappings must have an ID field. It's considered and ID field: a field called \"id\" or \"idClassName\" (i.e. for the \"Example\" class, idExample would be it's ID field) or any field annotated with @Id (javax.persistance.id.Id)");
		}
		
		return mapping;
	}
}
